## SOLID-принципы 


`Эффективный алгоритм` – основа работы эффективного программного обеспечения. 

Когда алгоритм уже есть, следующая задача – сделать так, чтобы ПО было разработано с использованием лучших методов проектирования и лучшей архитектуры. 

Специалисты, исследователи и эксперты определили лучшие практики эффективного проектирования программных приложений. 

Одной из наиболее популярных среди них являются принципы проектирования, известные под аббревиатурой `SOLID`.

Самыми известными и важными считаются принципы проектирования  Дяди Боба. 

Он представил много разных принципов проектирования, однако самых популярных всего 5, сокращенно их называют `SOLID-принципами`.

В основном они сфокусированы вокруг объектно-ориентированной парадигмы проектирования ПО.

Если учитывать эти рекомендации при разработке объектно-ориентированного ПО, код станет не таким сложным, снизится риск поломок, улучшится взаимодействие между различными объектами и код станет более гибким, читаемым и управляемым. 

SOLID-принципы дяди Боба расшифровываются следующим образом:

* S – Принцип единственной ответственности `Single Responsibility Principle`

* O – Принцип открытости/закрытости `Open‐Closed Principle`

* L – Принцип подстановки Барбары Лисков `Liskov Substitution Principle`

* I – Принцип разделения интерфейсов `Interface Segregation Principle`

* D – Принцип инверсии зависимостей `Dependency Inversion Principle`


### Принцип единственной ответственности (Single)

Принцип единой ответственности гласит, что у каждого класса должна быть только одна «ответственность» и он не должен брать на себя другие обязанности. 

Роберт К. Мартин объяснял его так: «У класса должна быть лишь одна причина для изменения». 

Давайте в качестве примера возьмем приложение телефонного справочника. 

Реализуем свой CRUD

Мы будем делать телефонный справочник, в котором будет класс `PhoneBase`.

 Он будет «нести ответственность» за ведение записей справочника, то есть телефонных номеров и названий организаций, которым принадлежат номера. 
 
 Ожидается, что класс будет выполнять следующие операции: добавлять новую запись (Name и Telephone Number), удалять существующую запись, изменять номер телефона, присвоенный сущности Name, и предоставлять поиск, который будет возвращать номер, присвоенный сущности Name.

 ```python
import json


class PhoneBase:
    def __init__(self):
        self.telephone_dict = {}

    def create_phone(self, name, number):
        self.telephone_dict[name] = number

    def read_number(self, name):
        return self.telephone_dict[name]

    def update_phone(self, name, number):
        self.telephone_dict[name] = number

    def delete_phone(self, name):
        self.telephone_dict.pop(name)

    def __str__(self):
        return json.dumps(self.telephone_dict, indent=4, ensure_ascii=False)


myPhoneBase = PhoneBase()

myPhoneBase.create_phone("Сергей", 123456)
myPhoneBase.create_phone("Егор", 678452)
print(myPhoneBase)

myPhoneBase.delete_phone("Сергей")
myPhoneBase.create_phone("Сергей", 123456)
myPhoneBase.update_phone("Егор", 776589)

print(myPhoneBase.read_number("Егор"))

print(myPhoneBase)
 ```

Вывод 
 ```
 {
    "Сергей": 123456,
    "Егор": 678452
}
========================================
{
    "Егор": 776589,
    "Сергей": 123456
}
 ```

 Сейчас наш класс `PhoneBase` выглядит хорошо, в нем точно реализованы ожидаемые функции:

А теперь скажем, что в проекте есть еще два требования – Сохранить содержимое справочника в базе данных и перенести содержимое справочника в файл. 

Теперь добавим еще два метода в класс PhoneBase:

```python
    def save_to_file(self, file_name, location):
              pass

    def persist_to_database(self, database_details):       
        pass
```

Так вот, именно сейчас мы нарушили принцип единственной ответственности. 

Добавив функции сохранения в базу данных и сохранения в файл, мы дали классу дополнительные обязанности, которые не входят в его основную зону ответственности. 

Теперь в классе есть дополнительные функции, которые могут привести к его изменению. В будущем, если появятся какие-то требования, связанные с сохранением данных, это может привести к изменениям в классе `PhoneBase`. 

Получается, что класс `PhoneBase` подвержен изменениям по причинам, которые не являются его основной ответственностью.

Принцип единственной ответственности требует от нас не добавлять дополнительные обязанности к классу, чтобы нам не приходилось менять класс, когда нам нужно изменить функционал сохранения справочника в базу данных или в файл. 

Мы можем передать экземпляр класса `PhoneBase` экземплярам этих классов и записать любые дополнительные функции в них.

Так мы гарантируем, что у класса `PhoneBase` есть лишь одна причина для изменения – это изменения в его основной «ответственности».

```python
class SaveToDatabase:
  def __init__(self, object_to_persist):
    pass

class SaveToFile:
  def __init__(self, object_to_save):
    pass

```